if SERVER then AddCSLuaFile( "IMiniGame_Init.lua" ) end

IMiniGame = {
	["Hooks"] = { },
	["Info"] = {
		["Name"] = "Base",
		["Version"] = "1.0",
		["up_date"] = "MidNight , 1st January 1970",
		["Author"] = {
			["Name"] = "Ningaglio",
			["Email"] = "Ningaglio@CitronGamers.com",
			["URL"] = "http://www.citrongamers.com"
		},
		["Info"] = "IMiniGame system",
		["Description"] = "Make some simple Minigames without the complexe coding!",
		["Icon"] = "gui/silkicons/brick_add"
	},
	["Vars"] = {
		["Loaded"] = nil,
		["Registered"] = { },
		["BaseTable"] = true,
		["BaseTables"] = { },
	},
	["Functions"] = {
		["OnPreLoad"] = function( Name )
			return true
		end,
		["OnPostLoad"] = function( Name )
			print( "[IMiniGame] " .. Name .. " has loaded!" )
		end,
		["OnUnload"] = function( Name )
			print( "[IMiniGame] " .. Name .. " has unloaded!" )
			return true
		end
	}
}

//----------------------\\
//		OVERIDE ALERT!  \\
//----------------------\\

_oldhookcall = gamemode.Call
 
function gamemode.Call(hookname, ...)
    _oldhookcall(hookname, ...)
	if IMiniGame.Vars.Loaded then
		if IMiniGame["Vars"]["Registered"][IMiniGame.Vars.Loaded]["Hooks"][hookname] then
			IMiniGame.Hooks[IMiniGame.Vars.Loaded][hookname](...)
		end
	end
end

//-------------------------\\
//		Util Functions     \\
//-------------------------\\


function IMiniGame.New( )
	local new_instance = table.Copy(IMiniGame)
	new_instance["Vars"] = { } -- Thats only for me ;)
	new_instance["Vars"]["BaseTable"] = false -- For the love of god don't change this ;)
	new_instance["Functions"] = {
		["OnPreLoad"] = function( ) return true end,
		["OnPostLoad"] = function( ) end,
		["OnUnload"] = function( ) return true end
	}
	return new_instance
end

function IMiniGame.Load( Name )
	if !IMiniGame["Vars"]["Loaded"] then
		if IMiniGame["Vars"]["Registered"][ Name ] then
		
			local _1 = IMiniGame["Functions"]["OnPreLoad"]( Name )
			local _2 = IMiniGame["Vars"]["Registered"][ Name ]["Functions"]["OnPreLoad"]( )
		
			if ( _1 and _2 ) then
			
				for name , func in pairs( IMiniGame["Vars"]["Registered"][ Name ]["Hooks"] ) do
					hook.Add( name , "IMiniGame:Loaded" , func )
				end
				
				IMiniGame["Functions"]["OnPostLoad"]( Name )
				IMiniGame["Vars"]["Registered"][ Name ]["Functions"]["OnPostLoad"]( )
				
				IMiniGame["Vars"]["Loaded"] = Name
				if SERVER then
					for k,v in pairs( player.GetAll() ) do
						v:KillSilent()
						v:Spawn()
					end
				end
			else
				print( "[IMiniGame] Did not load minigame!" )
			end
		end
	else
		IMiniGame.Unload( )
		IMiniGame.Load( Name )
	end
end

function IMiniGame.Unload( )
	if IMiniGame["Vars"]["Loaded"] != nil then
		local Name = IMiniGame["Vars"]["Loaded"]
		
		local _1 = IMiniGame["Functions"]["OnUnload"]( Name )
		local _2 = IMiniGame["Vars"]["Registered"][ Name ]["Functions"]["OnUnload"]( )
		
		if ( _1 and _2 ) then
			for name , func in pairs( IMiniGame["Vars"]["Registered"][ Name ]["Hooks"] ) do
				hook.Remove( name , "IMiniGame:Loaded" )
			end
			
			IMiniGame["Vars"]["Loaded"] = nil
			if SERVER then
				for k,v in pairs( player.GetAll() ) do
					v:KillSilent()
					v:Spawn()
				end
			end
		else
			print( "[IMiniGame] Did not unload minigame!" )
		end
	end
end

function IMiniGame.IsRegistered( n )
	if IMiniGame["Vars"]["Registered"][ n ] then
		return true
	else
		return false
	end
end

if SERVER then
	function IMiniGame.LoadEveryone( N )
		IMiniGame.Load( N )
		BroadcastLua( [[IMiniGame.Load( ]] .. N .. [[ )]] )
		return true
	end
	
	function IMiniGame.UnloadEveryone( N )
		IMiniGame.Unload( N )
		BroadcastLua( [[IMiniGame.Unload( ]] .. N .. [[ )]] )
		return true
	end
	
	concommand.Add( "IMiniGame_Load" , function( p , _ , a )
		if p:IsAdmin() then
			local s = string.Implode( " " , a )
			IMiniGame.LoadEveryone( s )
		end
	end)
	
	concommand.Add( "IMiniGame_UnLoad" , function( p , _ , a )
		if p:IsAdmin() then
			local s = string.Implode( " " , a )
			IMiniGame.UnloadEveryone( s )
		end
	end)
	
end

//-------------------------\\
//		Meta Functions     \\
//-------------------------\\

function IMiniGame:Derive( name )
	if self["Vars"]["BaseTable"] == false then
		if name == false then return false end
		if IMiniGame["Vars"]["BaseTables"][ name ] and IMiniGame["Vars"]["BaseTables"][ name ]["Vars"]["BaseTable"] == true then
			self["Hooks"] = IMiniGame["Vars"]["BaseTables"][ name ]["Hooks"]
			self["Vars"] = IMiniGame["Vars"]["BaseTables"][ name ]["Vars"]
			self["Functions"] = IMiniGame["Vars"]["BaseTables"][ name ]["Functions"]
		end
		return true
	end
	return false
end

function IMiniGame:RegisterBase( name ) -- Depricated ;)
	IMiniGame["Vars"]["BaseTables"][ name ] = self
	IMiniGame["Vars"]["BaseTables"][ name ]["Vars"]["BaseTable"] = true
	return true
end


function IMiniGame:Register( Name )
	function self.Hooks.GetGameDescription() return "[IMiniGame] " .. self.Info.Name end
	if Name then
		IMiniGame["Vars"]["Registered"][ Name ] = self
		self:RegisterBase( "Base" .. Name )
		return true
	else
		local Name = self["Info"]["Name"]
		IMiniGame["Vars"]["Registered"][ Name ] = self
		self:RegisterBase( "Base" .. Name )
		return false
	end
end

function IMiniGame:UnloadSelf( )
	if IMiniGame["Vars"]["Loaded"] == self["Info"]["Name"] then
		IMiniGame.Unload()
	end
end

//--------------------------\\
//		IMiniGame GUI       \\
//--------------------------\\

if CLIENT then

	function IMiniGame.OpenGUI()
		
		local DButton2
		local DButton1
		local DLabel1
		local DPanel2
		local DPanel1
		local DFrame1

		DFrame1 = vgui.Create('DFrame')
		DFrame1:SetSize(477, 236)
		DFrame1:SetPos(10, 8)
		DFrame1:SetTitle('IMiniGame GUI')
		DFrame1:SetSizable(true)
		DFrame1:SetDeleteOnClose(false)
		DFrame1:MakePopup()

		DPanel1 = vgui.Create('DTree')
		DPanel1:SetParent(DFrame1)
		DPanel1:SetSize(120, 209)
		DPanel1:SetPos(3, 24)
		
		local t = "Tag"
		local cur
		
		DPanel2 = vgui.Create('DPanel')
		DPanel2:SetParent(DFrame1)
		DPanel2:SetSize(350, 209)
		DPanel2:SetPos(125, 24)

		DLabel1 = vgui.Create('DLabel')
		DLabel1:SetParent(DPanel2)
		DLabel1:SetPos(6, 7)
		local function update()
			local info = IMiniGame["Vars"]["Registered"][ t ]["Info"]
			DLabel1:SetText([[Name : ]] .. info["Name"] .. [[ 
Version : ]] .. info["Version"] .. [[ 
Up_Date : ]] .. info["up_date"] .. [[ 
 
Author : ]] .. info["Author"]["Name"] .. [[ 
Email : ]] .. info["Author"]["Email"] .. [[ 
URL : ]] .. info["Author"]["URL"] .. [[ 
 
Info : ]] .. info["Info"] .. [[ 
Description : ]] .. info["Description"])
			DLabel1:SizeToContents()
		end
		update()

		
		for k,v in pairs( IMiniGame["Vars"]["Registered"] ) do
			local i = DPanel1:AddNode( k )
			function
				i:DoClick() t = k
				update()
			end
			i.Icon:SetImage( v["Info"]["Icon"] )
			cur = k
			update()
		end

		DButton1 = vgui.Create('DButton')
		DButton1:SetParent(DPanel2)
		DButton1:SetSize(156, 25)
		DButton1:SetPos(3, 179)
		DButton1:SetText('Load Selected Minigame')
		DButton1.DoClick = function()
			LocalPlayer():ConCommand( "IMiniGame_Load " .. t )
		end

		DButton2 = vgui.Create('DButton')
		DButton2:SetParent(DPanel2)
		DButton2:SetSize(180, 25)
		DButton2:SetPos(161, 179)
		DButton2:SetText('Unload Selected Minigame')
		DButton2.DoClick = function()
			LocalPlayer():ConCommand( "IMiniGame_UnLoad " .. t )
		end
	end
	
	concommand.Add( "IMiniGame_OpenGUI" , function( p )
		if p:IsAdmin() then
			IMiniGame.OpenGUI()
		end
	end)
	
end

// Auto loader , wanted by IRzilla

function IMiniGame.LoadScripts()
	print( "===========================" )
	print( "==== Loading IMiniGames====" )
	IMiniGame["Vars"]["Registered"] = { }
	IMiniGame["Vars"]["BaseTables"] = { }
	local list1 = file.FindInLua( "IMiniGames/*.lua")
	for _, file1 in pairs(list1) do
	   include( "IMiniGames/" .. file1)
	end
	print( "====== Done Loading ! =====" )
	print( "===========================" )
end

concommand.Add( "IMiniGame_ReloadScripts" , function( p )
	if p:IsAdmin() then
		IMiniGame.LoadScripts()
	end
end)

IMiniGame.LoadScripts()
